//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package io.lumine.xikage.mythicmobs.adapters.bukkit;

import io.lumine.xikage.mythicmobs.MythicMobs;
import io.lumine.xikage.mythicmobs.adapters.AbstractEntity;
import io.lumine.xikage.mythicmobs.adapters.AbstractLocation;
import io.lumine.xikage.mythicmobs.adapters.AbstractSkillAdapter;
import io.lumine.xikage.mythicmobs.adapters.AbstractVector;
import io.lumine.xikage.mythicmobs.io.ConfigManager;
import io.lumine.xikage.mythicmobs.logging.MythicLogger;
import io.lumine.xikage.mythicmobs.logging.MythicLogger.DebugLevel;
import io.lumine.xikage.mythicmobs.mobs.ActiveMob;
import io.lumine.xikage.mythicmobs.skills.SkillCaster;
import io.lumine.xikage.mythicmobs.skills.damage.DamageMetadata;
import io.lumine.xikage.mythicmobs.skills.mechanics.ShootMechanic;
import io.lumine.xikage.mythicmobs.skills.mechanics.ShootShulkerMechanic;
import io.lumine.xikage.mythicmobs.skills.mechanics.ShootFireballMechanic.FireballType;
import io.lumine.xikage.mythicmobs.skills.mechanics.ShootMechanic.ProjectileType;
import io.lumine.xikage.mythicmobs.util.MythicUtil;
import io.lumine.xikage.mythicmobs.utils.Schedulers;
import io.lumine.xikage.mythicmobs.utils.items.ItemFactory;
import io.lumine.xikage.mythicmobs.utils.numbers.Numbers;
import io.lumine.xikage.mythicmobs.utils.version.MinecraftVersions;
import io.lumine.xikage.mythicmobs.utils.version.ServerVersion;
import java.util.ArrayList;
import java.util.Iterator;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.EntityEffect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Creature;
import org.bukkit.entity.DragonFireball;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.Item;
import org.bukkit.entity.LargeFireball;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.ShulkerBullet;
import org.bukkit.entity.SmallFireball;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.WitherSkull;
import org.bukkit.event.block.BlockRedstoneEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Button;
import org.bukkit.material.Lever;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource;
import org.bukkit.util.Vector;

public class BukkitSkillAdapter implements AbstractSkillAdapter {
    public BukkitSkillAdapter() {
    }

    public void doDamage(DamageMetadata meta, AbstractEntity aTarget) {
        SkillCaster am = meta.getDamager();
        double damage = meta.getAmount();
        if (!aTarget.isDamageable()) {
            MythicLogger.debug(DebugLevel.MECHANIC, "Damage cancelled: target is not damageable", new Object[0]);
        } else {
            am.setUsingDamageSkill(true);
            am.getEntity().setMetadata("doing-skill-damage", true);
            aTarget.setMetadata("skill-damage", meta);
            if (am instanceof ActiveMob) {
                ((ActiveMob)am).setLastDamageSkillAmount(damage);
            }

            LivingEntity source = (LivingEntity)BukkitAdapter.adapt(am.getEntity());
            LivingEntity target = (LivingEntity)BukkitAdapter.adapt(aTarget);

            try {
                if (meta.getIgnoresArmor()) {
                    EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(BukkitAdapter.adapt(am.getEntity()), target, DamageCause.CUSTOM, damage);
                    Bukkit.getServer().getPluginManager().callEvent(event);
                    if (event.isCancelled()) {
                        MythicLogger.debug(DebugLevel.MECHANIC, "Mechanic damage event cancelled", new Object[0]);
                        am.setUsingDamageSkill(false);
                        return;
                    }

                    if (target.getHealth() - damage < 1.0D) {
                        target.setLastDamageCause(event);
                        target.setHealth(1.0E-4D);
                        if (meta.getPreventsKnockback()) {
                            target.damage(10.0D);
                        } else {
                            target.damage(10.0D, source);
                        }
                    } else {
                        target.setHealth(target.getHealth() - damage);
                        target.playEffect(EntityEffect.HURT);
                    }
                } else if (meta.getPreventsKnockback()) {
                    target.damage(damage);
                } else {
                    target.damage(damage, source);
                }
            } catch (Exception var12) {
                if (ConfigManager.debugLevel > 0) {
                    var12.printStackTrace();
                }
            } finally {
                am.getEntity().removeMetadata("doing-skill-damage");
                am.setUsingDamageSkill(false);
                aTarget.removeMetadata("skill-damage");
            }

            if (meta.getPreventsImmunity()) {
                target.setNoDamageTicks(0);
            }

        }
    }

    public void strikeLightning(AbstractLocation source) {
        BukkitAdapter.adapt(source.getWorld()).strikeLightning(BukkitAdapter.adapt(source));
    }

    public void strikeLightningEffect(AbstractLocation source) {
        BukkitAdapter.adapt(source.getWorld()).strikeLightningEffect(BukkitAdapter.adapt(source));
    }

    public void shootFireball(SkillCaster am, FireballType type, AbstractLocation target, float velocity, float yield, boolean incendiary, int fireTicks, boolean playsound, boolean charged, BukkitItemStack item) {
        Location t = BukkitAdapter.adapt(target);
        Entity l = BukkitAdapter.adapt(am.getEntity());
        Location loc = l.getLocation().clone().add(0.0D, 1.0D, 0.0D);
        Fireball fireball = null;
        Vector facing;
        if (l instanceof Creature && ((Creature)l).getTarget() == target) {
            switch(type) {
                case NORMAL:
                    fireball = (Fireball)((LivingEntity)l).launchProjectile(Fireball.class);
                    break;
                case SMALL:
                    fireball = (Fireball)((LivingEntity)l).launchProjectile(SmallFireball.class);
                    break;
                case LARGE:
                    fireball = (Fireball)((LivingEntity)l).launchProjectile(LargeFireball.class);
                    break;
                case WITHER:
                    fireball = (Fireball)((LivingEntity)l).launchProjectile(WitherSkull.class);
                    break;
                case DRAGON:
                    fireball = (Fireball)((LivingEntity)l).launchProjectile(DragonFireball.class);
                    break;
            }
        } else {
            facing = t.toVector().subtract(loc.toVector()).normalize();
            double yaw = Math.toDegrees(Math.atan2(-facing.getX(), facing.getZ()));
            double pitch = Math.toDegrees(-Math.asin(facing.getY()));
            loc.setYaw((float)yaw);
            loc.setPitch((float)pitch);
            loc.add(facing.multiply(2));
            switch(type) {
                case NORMAL:
                    fireball = (Fireball)loc.getWorld().spawn(loc, Fireball.class);
                    break;
                case SMALL:
                    fireball = (Fireball)loc.getWorld().spawn(loc, SmallFireball.class);
                    break;
                case LARGE:
                    fireball = (Fireball)loc.getWorld().spawn(loc, LargeFireball.class);
                    break;
                case WITHER:
                    fireball = (Fireball)loc.getWorld().spawn(loc, WitherSkull.class);
                    ((WitherSkull)fireball).setCharged(charged);
                    break;
                case DRAGON:
                    fireball = (Fireball)loc.getWorld().spawn(loc, DragonFireball.class);
                    break;
            }
        }

        if (playsound) {
            l.getWorld().playEffect(l.getLocation(), Effect.GHAST_SHOOT, 0);
        }

        facing = t.toVector().subtract(loc.toVector()).normalize().multiply(velocity);
        fireball.setVelocity(facing);
        fireball.setBounce(false);
        fireball.setIsIncendiary(incendiary);
        fireball.setFireTicks(fireTicks);
        fireball.setYield(yield);
        if (l instanceof LivingEntity) {
            fireball.setShooter((LivingEntity)l);
        }

    }

    public AbstractEntity shootProjectile(SkillCaster caster, AbstractLocation target, AbstractLocation origin, Class<? extends Projectile> projectileClass, AbstractVector velocity, ShootMechanic mechanic) {
        LivingEntity l = (LivingEntity)caster.getEntity().getBukkitEntity();
        Location fTarget = BukkitAdapter.adapt(target);
        Vector vector = BukkitAdapter.adapt(velocity);
        if (Double.isNaN(vector.getX())) {
            vector.setX(0);
        }

        if (Double.isNaN(vector.getY())) {
            vector.setY(0);
        }

        if (Double.isNaN(vector.getZ())) {
            vector.setZ(0);
        }

        Projectile projectile;
        if (target == null) {
            projectile = l.launchProjectile(projectileClass, vector);
        } else if (mechanic.getFromOrigin()) {
            Location fOrigin = BukkitAdapter.adapt(origin);
            projectile = (Projectile)fTarget.getWorld().spawn(fOrigin, projectileClass);
            projectile.setVelocity(vector);
        } else {
            projectile = l.launchProjectile(projectileClass, vector);
        }

         if (projectile instanceof ThrownPotion) {
            ItemFactory potionItem;
            if (mechanic.getProjectileType() == ProjectileType.LINGERING_POTION) {
                potionItem = ItemFactory.of(Material.LINGERING_POTION);
            } else {
                potionItem = ItemFactory.of(Material.SPLASH_POTION);
            }

            PotionEffectType potionType = PotionEffectType.getByName(mechanic.getPotionEffectType().get(caster));
            int potionDuration = mechanic.getPotionDuration().get(caster);
            int potionAmplifier = mechanic.getPotionAmplifier().get(caster);
            potionItem.potionEffect(potionType, potionDuration, potionAmplifier);
            potionItem.color(mechanic.getPotionColor());
            ((ThrownPotion)projectile).setItem(potionItem.build());
        }

        projectile.setBounce(mechanic.getBounce());
        projectile.setShooter(l);
        return BukkitAdapter.adapt(projectile);
    }

    public AbstractEntity shootArcProjectile(SkillCaster caster, AbstractLocation target, AbstractLocation origin, Class<? extends Projectile> projectileClass, float velocity, boolean fromOrigin) {
        boolean gravity = true;
        LivingEntity l = (LivingEntity)caster.getEntity().getBukkitEntity();
        Location to = BukkitAdapter.adapt(target);
        Projectile projectile;
        Location from;
        if (fromOrigin) {
            Location fOrigin = BukkitAdapter.adapt(origin);
            from = fOrigin;
            projectile = (Projectile)fOrigin.getWorld().spawn(fOrigin, projectileClass);
        } else {
            from = l.getLocation();
            projectile = l.launchProjectile(projectileClass);
        }

        projectile.setBounce(false);
        projectile.setShooter(l);
        Vector test = to.clone().subtract(from).toVector();
        Double elevation = test.getY();
        Double launchAngle = MythicUtil.calculateLaunchAngle(from, to, (double)velocity, elevation, 20.0D);
        Double distance = Math.sqrt(Math.pow(test.getX(), 2.0D) + Math.pow(test.getZ(), 2.0D));
        if (launchAngle == null) {
            launchAngle = Math.atan((40.0D * elevation + Math.pow((double)velocity, 2.0D)) / (40.0D * elevation + 2.0D * Math.pow((double)velocity, 2.0D)));
        }

        Double hangtime = MythicUtil.calculateHangtime(launchAngle, (double)velocity, elevation, 20.0D);
        test.setY(Math.tan(launchAngle) * distance);
        test = MythicUtil.normalizeVector(test);
        velocity = (float)((double)velocity + 1.188D * Math.pow(hangtime, 2.0D) + (Numbers.randomDouble() - 0.8D) / 2.0D);
        test = test.multiply((double)velocity / 20.0D);
        projectile.setVelocity(test);
        return BukkitAdapter.adapt(projectile);
    }

    public AbstractEntity rainProjectile(SkillCaster caster, AbstractLocation source, Class<? extends Projectile> projectileClass, float velocity) {
        LivingEntity l = (LivingEntity)caster.getEntity().getBukkitEntity();
        Location s = BukkitAdapter.adapt(source);
        Projectile projectile = (Projectile)l.getWorld().spawn(s, projectileClass);
        Vector v = s.clone().add(0.0D, -1.0D, 0.0D).toVector().subtract(s.toVector()).normalize().multiply(velocity);
        projectile.setVelocity(v);
        projectile.setBounce(false);
        projectile.setShooter(l);
        return BukkitAdapter.adapt(projectile);
    }

    public AbstractEntity shootShulkerBullet(SkillCaster caster, AbstractEntity target, AbstractLocation origin, ShootShulkerMechanic mechanic) {
        LivingEntity l = (LivingEntity)caster.getEntity().getBukkitEntity();
        Entity eTarget = BukkitAdapter.adapt(target);
        ShulkerBullet projectile;
        if (mechanic.getFromOrigin()) {
            Location fOrigin = BukkitAdapter.adapt(origin);
            projectile = (ShulkerBullet)eTarget.getWorld().spawn(fOrigin, ShulkerBullet.class);
        } else {
            projectile = (ShulkerBullet)l.launchProjectile(ShulkerBullet.class);
        }

        projectile.setTarget(eTarget);
        projectile.setBounce(mechanic.getBounce());
        projectile.setShooter(l);
        return BukkitAdapter.adapt(projectile);
    }

    public void throwSkill(AbstractLocation source, AbstractEntity target, float velocity, float velocityY) {
        Vector V = BukkitAdapter.adapt(target.getLocation()).toVector().subtract(BukkitAdapter.adapt(source).toVector()).normalize().multiply(velocity);
        if (velocity == 0.0F) {
            V.setY(velocityY);
        } else {
            V.setY((double)velocityY + V.getY());
        }

        if (V.length() > 4.0D) {
            V = V.normalize().multiply(4);
        }

        if (Double.isNaN(V.getX())) {
            V.setX(0);
        }

        if (Double.isNaN(V.getY())) {
            V.setY(0);
        }

        if (Double.isNaN(V.getZ())) {
            V.setZ(0);
        }

        target.getBukkitEntity().setVelocity(V);
    }

    public void itemSprayEffect(AbstractLocation source, ItemStack item, int amount, int duration, double force, double yForce, double radius, double yOffset, boolean allowPickup) {
        Location l = BukkitAdapter.adapt(source);
        ItemStack is = item;
        item.setAmount(1);
        Location loc = l.clone().add(0.0D, yOffset, 0.0D);
        Item[] items = new Item[amount];
        if (radius <= 0.0D) {
            for(int i = 0; i < amount; ++i) {
                items[i] = loc.getWorld().dropItem(loc, is);
                items[i].setVelocity(new Vector((Numbers.randomDouble() - 0.5D) * force, (Numbers.randomDouble() - 0.5D) * yForce, (Numbers.randomDouble() - 0.5D) * force));

                try {
                    if (!allowPickup) {
                        items[i].setPickupDelay(32767);
                        items[i].setTicksLived(5800);
                    }
                } catch (Exception var22) {
                }
            }
        } else {
            for(int i = 0; i < amount; ++i) {
                Location lx = loc.clone();
                lx.setX(lx.getX() - radius + Numbers.randomDouble() * radius * 2.0D);
                lx.setZ(lx.getZ() - radius + Numbers.randomDouble() * radius * 2.0D);
                items[i] = lx.getWorld().dropItem(lx, is);
                items[i].setVelocity(new Vector((Numbers.randomDouble() - 0.5D) * force, (Numbers.randomDouble() - 0.5D) * yForce, (Numbers.randomDouble() - 0.5D) * force));

                try {
                    if (!allowPickup) {
                        items[i].setPickupDelay(32767);
                        items[i].setTicksLived(5800);
                    }
                } catch (Exception var21) {
                }
            }
        }

        Schedulers.sync().runLater(() -> {
            for(int i = 0; i < items.length; ++i) {
                items[i].remove();
            }

        }, (long)duration);
    }

    public void playSmokeEffect(AbstractLocation source, int direction) {
        BukkitAdapter.adapt(source).getWorld().playEffect(BukkitAdapter.adapt(source), Effect.SMOKE, direction);
    }

    public void pushButton(SkillCaster am, AbstractLocation location) {
        Block block = BukkitAdapter.adapt(location).getWorld().getBlockAt(BukkitAdapter.adapt(location));
        MythicLogger.debug(DebugLevel.MECHANIC, "Executing pushbutton mechanic @ " + location.toString() + "", new Object[0]);

        try {
            if (ServerVersion.isAfterOrEq(MinecraftVersions.v1_15)) {
                MythicMobs.inst().getVolatileCodeHandler().getBlockHandler().togglePowerable(location, 20L);
            } else {
                Button button = new Button(Material.STONE_BUTTON, block.getData());
                button.setPowered(true);
                BlockRedstoneEvent toggle = new BlockRedstoneEvent(block, 0, 1);
                Bukkit.getPluginManager().callEvent(toggle);
                MythicMobs.inst().getVolatileCodeHandler().applyPhysics(block);
                MythicMobs.inst().getVolatileCodeHandler().applyPhysics(block.getRelative(button.getAttachedFace()));
                Schedulers.sync().runLater(() -> {
                    try {
                        block.getChunk().load();
                        button.setPowered(false);
                        BlockRedstoneEvent toggle2 = new BlockRedstoneEvent(block, 0, 1);
                        Bukkit.getPluginManager().callEvent(toggle2);
                        MythicMobs.inst().getVolatileCodeHandler().applyPhysics(block);
                        MythicMobs.inst().getVolatileCodeHandler().applyPhysics(block.getRelative(button.getAttachedFace()));
                    } catch (Exception var3) {
                        var3.printStackTrace();
                    }

                }, 20L);
            }

        } catch (Exception var6) {
            MythicLogger.error("A pushbutton skill is improperly configured: block is not a button.");
            var6.printStackTrace();
        }
    }

    public void toggleLever(SkillCaster am, AbstractLocation location, int duration) {
        Block block = BukkitAdapter.adapt(location).getWorld().getBlockAt(BukkitAdapter.adapt(location));
        MythicLogger.debug(DebugLevel.MECHANIC, "Executing togglelever mechanic @ " + location.toString() + " duration=" + duration, new Object[0]);

        try {
            if (ServerVersion.isAfterOrEq(MinecraftVersions.v1_15)) {
                MythicMobs.inst().getVolatileCodeHandler().getBlockHandler().togglePowerable(location, (long)duration);
            } else {
                Lever button = new Lever(Material.LEVER, block.getData());
                button.setPowered(true);
                BlockRedstoneEvent toggle = new BlockRedstoneEvent(block, 0, 1);
                Bukkit.getPluginManager().callEvent(toggle);
                BukkitSkillAdapter.LeverUnswitcher BU = new BukkitSkillAdapter.LeverUnswitcher(block);
                Bukkit.getScheduler().scheduleSyncDelayedTask(MythicMobs.inst(), BU, (long)duration);
            }
        } catch (Exception var8) {
            MythicLogger.error("A ToggleLever skill is improperly configured: block is not a button.");
        }

    }

    public void executeVolley(SkillCaster am, AbstractLocation t, int amount, float velocity, float spread, int fireTicks, int removeDelay) {
        if (am.getEntity().getBukkitEntity() instanceof ProjectileSource) {
            ProjectileSource source = (ProjectileSource)am.getEntity().getBukkitEntity();
            Location target = BukkitAdapter.adapt(t);
            Location spawn = BukkitAdapter.adapt(am.getLocation()).clone();
            spawn.setY(spawn.getY() + 3.0D);
            Vector v;
            if (target == null) {
                v = spawn.getDirection();
            } else {
                v = target.toVector().subtract(spawn.toVector()).normalize();
            }

            final ArrayList<Arrow> arrowList = new ArrayList();

            for(int i = 0; i < amount; ++i) {
                Arrow a = spawn.getWorld().spawnArrow(spawn, v, velocity, spread / 10.0F);
                a.setVelocity(a.getVelocity());
                if (am.getEntity() != null) {
                    a.setShooter(source);
                }

                if (fireTicks > 0) {
                    a.setFireTicks(fireTicks);
                }

                arrowList.add(a);
            }

            Bukkit.getScheduler().scheduleSyncDelayedTask(MythicMobs.inst(), new Runnable() {
                public void run() {
                    Iterator var1 = arrowList.iterator();

                    while(var1.hasNext()) {
                        Arrow a = (Arrow)var1.next();
                        a.remove();
                    }

                    arrowList.clear();
                }
            }, (long)removeDelay);
        }
    }

    public void sendToastNotification(SkillCaster caster, String message) {
    }

    private static class LeverUnswitcher implements Runnable {
        private Block block;

        public LeverUnswitcher(Block block) {
            this.block = block;
        }

        public void run() {
            try {
                if (!this.block.getChunk().isLoaded()) {
                    this.block.getChunk().load();
                }

                Lever button = new Lever(Material.LEVER, this.block.getData());
                button.setPowered(false);
                BlockRedstoneEvent toggle = new BlockRedstoneEvent(this.block, 0, 1);
                Bukkit.getPluginManager().callEvent(toggle);
            } catch (Exception var3) {
            }

        }
    }
}
